package com.lpf.test01;

import cn.hutool.json.JSONUtil;
import com.lpf.flowable.FlowableUIApplication;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import javax.annotation.Resource;
import java.util.*;

@RunWith(SpringRunner.class)
//这里的Application是springboot的启动类名
@SpringBootTest(classes = FlowableUIApplication.class)
@WebAppConfiguration
public class 多人会签测试 {

    // 流程引擎
    @Resource
    private ProcessEngine processEngine;
    // 用户以及组管理服务
    @Resource
    private IdentityService identityService;
    // 模型服务
    @Resource
    private ModelService modelService;
    // 部署服务
    @Resource
    private RepositoryService repositoryService;
    // 流程实例服务
    @Resource
    private RuntimeService runtimeService;
    // 流程节点任务服务
    @Resource
    private TaskService taskService;
    // 历史数据服务
    @Resource
    private HistoryService historyService;

    /**
     * 流程部署
     * <p>
     * 流程ID，来自 ACT_DE_MODEL
     */
    @Test
    public void deploy() {

        String modelId = "9ae5afe4-c106-11ea-b949-5afb84df620e";

        // 根据模型 ID 获取模型
        Model modelData = modelService.getModel(modelId);

        byte[] bytes = modelService.getBpmnXML(modelData);
        if (bytes == null) {
            System.out.println("模型数据为空，请先设计流程并成功保存，再进行发布");
        }

        BpmnModel model = modelService.getBpmnModel(modelData);
        if (model.getProcesses().size() == 0) {
            System.out.println("数据模型不符要求，请至少设计一条主线流程");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
        String processName = modelData.getName() + ".bpmn20.xml";

        // 部署流程
        Deployment deploy = repositoryService.createDeployment()
                .name(modelData.getName())
                .addBytes(processName, bpmnBytes)
                .deploy();

        // TODO: 2020/7/9
        System.out.println(JSONUtil.toJsonPrettyStr(deploy));
    }

    /**
     *
     */
    @Test
    public void start() {

        String deployId = "DuoLuJingHuiTui:1:25004";
        String dataKey = "445566";

        // 设置发起人
        identityService.setAuthenticatedUserId("startPerson");
        // 根据流程 ID 启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(deployId, dataKey);

        System.out.println("ProcessInstanceId: " + processInstance.getProcessInstanceId());
    }

    /**
     * 根据办理人获取任务列表
     */
    @Test
    public void getRuntimeBusinessKeyByUserId() {
        String userId = "qp";

        List<Map<String, Object>> idList = new ArrayList<>();
        // 根据用户获取正在进行的任务
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).list();
        tasks.forEach(task -> {
            Map<String, Object> data = new HashMap<>();
            // 根据任务获取流程实例
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            // 获取流程实例中的业务键
            data.put("businessKey", processInstance.getBusinessKey());
            // 获取任务 Id
            data.put("taskId", task.getId());
            // 流程定义名称
            data.put("processInstanceName", processInstance.getProcessDefinitionName());
            // 流程开始时间
            data.put("startTime", processInstance.getStartTime());
            idList.add(data);
        });

        System.out.println(JSONUtil.toJsonPrettyStr(idList));
    }

    /**
     * 根据办理人获取任务列表
     */
    @Test
    public void getRuntimeBusinessKeyByGroupId() {
        String groupId = "group3";

        List<Map<String, Object>> idList = new ArrayList<>();
        // 根据用户获取正在进行的任务
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(groupId).list();
        tasks.forEach(task -> {
            Map<String, Object> data = new HashMap<>();
            // 根据任务获取流程实例
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            // 获取流程实例中的业务键
            data.put("businessKey", processInstance.getBusinessKey());
            // 获取任务 Id
            data.put("taskId", task.getId());
            // 流程定义名称
            data.put("processInstanceName", processInstance.getProcessDefinitionName());
            // 流程开始时间
            data.put("startTime", processInstance.getStartTime());
            idList.add(data);
        });

        System.out.println(JSONUtil.toJsonPrettyStr(idList));
    }


    /**
     *
     */
    @Test
    public void 第一审核人节点() {
        String taskId = "30007";
        // 设置审核人（必须在进入 第二审核人节点 之前设置）
        taskService.setVariable(taskId, "reviewer", "bbb");
        // 完成任务
        taskService.complete(taskId);
    }

    /**
     *
     */
    @Test
    public void 第二审核人节点() {
        String taskId = "35004";
        taskService.complete(taskId);
    }

    /**
     *
     */
    @Test
    public void 第三审核人节点() {
        String taskId = "37503";
        // 添加分支条件
        Map<String, Object> map = new HashMap<>();
        map.put("assignee", "admin");
        // 设置审核人
        taskService.setAssignee(taskId, "lpf");
        taskService.complete(taskId, map);
    }

    /**
     *
     */
    @Test
    public void 第四审核人节点() {
        String taskId = "40007";

        List<String> assigneeList = Arrays.asList("qp", "wk", "cqg");
        taskService.setVariable(taskId, "assigneeList", assigneeList);

        // 设置审核人
        taskService.setAssignee(taskId, "wt");
        taskService.complete(taskId);
    }

    /**
     *
     */
    @Test
    public void 会签节点() {
        String taskId = "45027";

        String processInstanceId = taskService.createTaskQuery().taskId(taskId).singleResult().getProcessInstanceId();
        // 设置审核人
        taskService.setAssignee(taskId, "jiji");
        taskService.addComment(taskId, processInstanceId, "第二次会签");
        // 完成任务
        taskService.complete(taskId);
    }


}
